from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import Optional, List, Dict, Any, Union
from datetime import datetime

from models.flight_log import FlightLog as FlightLogModel
from models.drone import Drone
from models.task import Task
from schemas.flight_log import (
    FlightLog, FlightLogCreate, FlightLogUpdate, FlightLogList,
    FlightTrajectory, FlightTrajectoryPoint
)
from database import get_db

router = APIRouter()


@router.post("/", response_model=FlightLog)
def create_flight_log(
    flight_log: FlightLogCreate,
    db: Session = Depends(get_db)
):
    """
    创建飞行日志
    
    - **drone_id**: 无人机ID（必填）
    - **task_id**: 任务ID（可选）
    - **latitude/longitude/altitude**: 位置信息（必填）
    - **speed/heading**: 飞行状态（必填）
    - **battery_voltage**: 电池电压（必填）
    - 其他字段为可选
    """
    try:
        # 验证无人机是否存在
        drone = db.query(Drone).filter(Drone.id == flight_log.drone_id).first()
        if not drone:
            raise HTTPException(status_code=404, detail="无人机不存在")
        
        # 如果提供了task_id，验证任务是否存在
        if flight_log.task_id:
            task = db.query(Task).filter(Task.id == flight_log.task_id).first()
            if not task:
                raise HTTPException(status_code=404, detail="任务不存在")
        
        # 创建飞行日志
        db_flight_log = FlightLogModel(**flight_log.model_dump())
        db.add(db_flight_log)
        db.commit()
        db.refresh(db_flight_log)
        
        # 构建响应
        response = FlightLog(
            id=db_flight_log.id,
            drone_id=db_flight_log.drone_id,
            task_id=db_flight_log.task_id,
            latitude=db_flight_log.latitude,
            longitude=db_flight_log.longitude,
            altitude=db_flight_log.altitude,
            speed=db_flight_log.speed,
            heading=db_flight_log.heading,
            roll=db_flight_log.roll,
            pitch=db_flight_log.pitch,
            yaw=db_flight_log.yaw,
            motor_speed_1=db_flight_log.motor_speed_1,
            motor_speed_2=db_flight_log.motor_speed_2,
            motor_speed_3=db_flight_log.motor_speed_3,
            motor_speed_4=db_flight_log.motor_speed_4,
            battery_voltage=db_flight_log.battery_voltage,
            battery_current=db_flight_log.battery_current,
            battery_percentage=db_flight_log.battery_percentage,
            temperature=db_flight_log.temperature,
            humidity=db_flight_log.humidity,
            wind_speed=db_flight_log.wind_speed,
            wind_direction=db_flight_log.wind_direction,
            cpu_temperature=db_flight_log.cpu_temperature,
            gpu_temperature=db_flight_log.gpu_temperature,
            ram_usage=db_flight_log.ram_usage,
            task_progress=db_flight_log.task_progress,
            current_waypoint_index=db_flight_log.current_waypoint_index,
            flight_mode=db_flight_log.flight_mode,
            gps_satellites=db_flight_log.gps_satellites,
            gps_accuracy=db_flight_log.gps_accuracy,
            error_code=db_flight_log.error_code,
            error_message=db_flight_log.error_message,
            extended_data=db_flight_log.extended_data,
            record_time=db_flight_log.record_time,
            created_at=db_flight_log.created_at,
            updated_at=db_flight_log.updated_at,
            drone_name=drone.name,
            task_name=task.name if flight_log.task_id and task else None
        )
        
        return response
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"创建飞行日志失败: {str(e)}")


@router.get("/", response_model=Dict[str, Any])
def get_flight_logs(
    db: Session = Depends(get_db),
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    drone_id: Union[str, int, None] = Query(None, description="无人机ID"),
    task_id: Union[str, int, None] = Query(None, description="任务ID"),
    start_time: Optional[datetime] = Query(None, description="开始时间"),
    end_time: Optional[datetime] = Query(None, description="结束时间"),
    error_only: Optional[bool] = Query(False, description="仅显示有错误的日志")
):
    # 处理空字符串输入
    if drone_id == "":
        drone_id = None
    elif drone_id is not None:
        drone_id = int(drone_id)
        
    if task_id == "":
        task_id = None
    elif task_id is not None:
        task_id = int(task_id)
    """
    获取飞行日志列表
    
    支持按无人机、任务、时间范围筛选，以及分页查询
    """
    try:
        # 构建查询
        query = db.query(
            FlightLogModel,
            Drone.name.label('drone_name'),
            Task.name.label('task_name')
        ).join(
            Drone, FlightLogModel.drone_id == Drone.id,
            isouter=True
        ).join(
            Task, FlightLogModel.task_id == Task.id,
            isouter=True
        )
        
        # 应用筛选条件
        if drone_id:
            query = query.filter(FlightLogModel.drone_id == drone_id)
        if task_id:
            query = query.filter(FlightLogModel.task_id == task_id)
        if start_time:
            query = query.filter(FlightLogModel.record_time >= start_time)
        if end_time:
            query = query.filter(FlightLogModel.record_time <= end_time)
        if error_only:
            query = query.filter(FlightLogModel.error_code.isnot(None))
        
        # 计算总数
        total = query.count()
        
        # 分页查询
        offset = (page - 1) * page_size
        results = query.order_by(
            FlightLogModel.record_time.desc()
        ).offset(offset).limit(page_size).all()
        
        # 构建响应数据
        items = []
        for log, drone_name, task_name in results:
            item = {
                "id": log.id,
                "drone_id": log.drone_id,
                "drone_name": drone_name,
                "task_id": log.task_id,
                "task_name": task_name,
                "latitude": log.latitude,
                "longitude": log.longitude,
                "altitude": log.altitude,
                "speed": log.speed,
                "heading": log.heading,
                "battery_voltage": log.battery_voltage,
                "battery_percentage": log.battery_percentage,
                "flight_mode": log.flight_mode,
                "error_code": log.error_code,
                "error_message": log.error_message,
                "record_time": log.record_time.isoformat() if log.record_time else None,
                "created_at": log.created_at.isoformat()
            }
            items.append(item)
        
        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "items": items,
                "total": total,
                "page": page,
                "page_size": page_size,
                "pages": (total + page_size - 1) // page_size
            }
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取飞行日志失败: {str(e)}")


@router.get("/trajectory", response_model=Dict[str, Any])
def get_flight_trajectory(
    drone_id: Union[str, int, None] = Query(..., description="无人机ID"),
    task_id: Union[str, int, None] = Query(None, description="任务ID"),
    start_time: Optional[datetime] = Query(None, description="开始时间"),
    end_time: Optional[datetime] = Query(None, description="结束时间"),
    max_points: Optional[int] = Query(1000, ge=100, le=10000, description="最大轨迹点数量"),
    db: Session = Depends(get_db)
):
    # 处理空字符串输入
    if drone_id == "":
        raise HTTPException(status_code=400, detail="无人机ID不能为空")
    elif drone_id is not None:
        drone_id = int(drone_id)
        
    if task_id == "":
        task_id = None
    elif task_id is not None:
        task_id = int(task_id)
    """
    获取无人机飞行轨迹
    
    按任务或时间范围获取无人机的飞行轨迹数据
    """
    try:
        # 验证无人机是否存在
        drone = db.query(Drone).filter(Drone.id == drone_id).first()
        if not drone:
            raise HTTPException(status_code=404, detail="无人机不存在")
        
        # 构建查询
        query = db.query(FlightLogModel).filter(
            FlightLogModel.drone_id == drone_id
        )
        
        # 应用筛选条件
        if task_id:
            query = query.filter(FlightLogModel.task_id == task_id)
        if start_time:
            query = query.filter(FlightLogModel.record_time >= start_time)
        if end_time:
            query = query.filter(FlightLogModel.record_time <= end_time)
        
        # 获取总记录数
        total_count = query.count()
        
        # 如果记录数超过最大点数，计算采样间隔
        if total_count > max_points:
            interval = total_count // max_points
            logs = query.order_by(
                FlightLogModel.record_time
            ).offset(0).limit(total_count).all()[::interval]
        else:
            logs = query.order_by(
                FlightLogModel.record_time
            ).all()
        
        # 构建轨迹点
        points = []
        for log in logs:
            point = {
                "timestamp": log.record_time.isoformat() if log.record_time else None,
                "latitude": log.latitude,
                "longitude": log.longitude,
                "altitude": log.altitude,
                "speed": log.speed
            }
            points.append(point)
        
        # 获取任务信息
        task_name = None
        if task_id:
            task = db.query(Task).filter(Task.id == task_id).first()
            task_name = task.name if task else None
        
        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "drone_id": drone_id,
                "drone_name": drone.name,
                "task_id": task_id,
                "task_name": task_name,
                "start_time": logs[0].record_time.isoformat() if logs else None,
                "end_time": logs[-1].record_time.isoformat() if logs else None,
                "points": points
            }
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取飞行轨迹失败: {str(e)}")


@router.get("/statistics", response_model=Dict[str, Any])
def get_flight_statistics(
    drone_id: Union[str, int, None] = Query(None, description="无人机ID"),
    task_id: Union[str, int, None] = Query(None, description="任务ID"),
    start_time: Optional[datetime] = Query(None, description="开始时间"),
    end_time: Optional[datetime] = Query(None, description="结束时间"),
    db: Session = Depends(get_db)
):
    # 处理空字符串输入
    if drone_id == "":
        drone_id = None
    elif drone_id is not None:
        drone_id = int(drone_id)
        
    if task_id == "":
        task_id = None
    elif task_id is not None:
        task_id = int(task_id)
    """
    获取飞行统计数据
    
    包括飞行时间、平均速度、最大高度、电池使用情况等统计信息
    """
    try:
        # 构建查询
        query = db.query(FlightLogModel)
        
        # 应用筛选条件
        if drone_id:
            query = query.filter(FlightLogModel.drone_id == drone_id)
        if task_id:
            query = query.filter(FlightLogModel.task_id == task_id)
        if start_time:
            query = query.filter(FlightLogModel.record_time >= start_time)
        if end_time:
            query = query.filter(FlightLogModel.record_time <= end_time)
        
        # 获取所有符合条件的日志
        logs = query.order_by(FlightLogModel.record_time).all()
        
        if not logs:
            return {
                "code": 200,
                "message": "获取成功",
                "data": {
                    "total_flights": 0,
                    "total_flight_time": 0,
                    "avg_speed": 0,
                    "max_speed": 0,
                    "max_altitude": 0,
                    "battery_usage": 0,
                    "error_count": 0
                }
            }
        
        # 计算统计数据
        total_flight_time = 0
        speeds = []
        altitudes = []
        error_count = 0
        battery_start = None
        battery_end = None
        
        for i, log in enumerate(logs):
            speeds.append(log.speed)
            altitudes.append(log.altitude)
            if log.error_code:
                error_count += 1
            
            # 计算飞行时间（基于记录间隔）
            if i > 0:
                time_diff = (log.record_time - logs[i-1].record_time).total_seconds()
                if time_diff < 300:  # 过滤异常大的时间间隔
                    total_flight_time += time_diff
            
            # 记录电池起始和结束状态
            if i == 0 and log.battery_percentage is not None:
                battery_start = log.battery_percentage
            if log.battery_percentage is not None:
                battery_end = log.battery_percentage
        
        # 计算电池使用情况
        battery_usage = 0
        if battery_start and battery_end:
            battery_usage = max(0, battery_start - battery_end)
        
        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "total_flights": len(set(log.drone_id for log in logs)),
                "total_flight_time": round(total_flight_time / 60, 2),  # 转换为分钟
                "avg_speed": round(sum(speeds) / len(speeds), 2) if speeds else 0,
                "max_speed": max(speeds) if speeds else 0,
                "max_altitude": max(altitudes) if altitudes else 0,
                "battery_usage": battery_usage,
                "error_count": error_count
            }
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取飞行统计失败: {str(e)}")